import Event from '../../libs/class/Event.js';

/**
 * 前缀和管理
 * @Author liruilin
 * @Date   2022/7/15
 */
class PrefixSumManage extends Event  {
    constructor({
        target,
        property
    }){
        super()
        this.target = target
        this.propertyKey = property
        // 防越界，也就是防止 prefixSum[length - 1] 为空的情况 
        this.prefixSum[-1] = 0 
    }
    /*    前缀和数组    */
    get prefixSum(){
        return this.target[this.propertyKey]
    }
    
    set prefixSum(value){
        this.target[this.propertyKey] = value
    }
    
    get length(){
        return this.prefixSum.length
    }
    /*    前缀和数组 END */
    
    /**
     * 修改前缀和，功能同 Array.splice
     * @param {Number} index
     * @param {Number} count
     * @param {IArguments} update
     */
    splice(index, count, ...update){
        // 提出要修改的前缀和
        let updateData = this.prefixSum.slice(index, index + count)
        // 要更改的前缀和起点值(上一位，也就是数组 [1,2,4,8] 更新 [4,8]，起点就是下标 2 )
        let updateStartPoint = this.prefixSum[index - 1]
        // 计算更新数据的前缀和数组
        let updatePrefixSumData = this.calculPrefixSum(update, updateStartPoint)
        // 修改
        if(updatePrefixSumData.length){
            this.prefixSum.splice(index, count, ...updatePrefixSumData)
        }else {
            this.prefixSum.splice(index, count)
        }
        /**
         * 如有被修改的前缀和，那么代表着后续所有项都需要 加减 修改后的差距值
         */
        if(updateData.length){
            // 更新数据最后一项减去原来被更新数据最后一项 即得到差距值(正/负数)
            let drift = updatePrefixSumData[updatePrefixSumData.length - 1] - updateData[updateData.length - 1]
            let length = this.prefixSum.length
            index = index + count
            while(index < length){
                this.prefixSum[index] += drift
                index ++
                console.log(1)
            }
        }
        // 通知改变
        this.$emit('updateChange')
    }
    /**
     * 二分搜索查找最近前缀和位置
     * @param {Object} about 
     * @param {Object} aboutIndex 查找前缀和附近位置，有值可以减少运算耗时
     */
    binarySearch(about, aboutIndex){
        let min = 0,
            max = this.length - 1
        if(aboutIndex){
            if(this.prefixSum[aboutIndex] > about){
                min = aboutIndex
            }else {
                max = aboutIndex
            }
        }
        // 二分搜索
        while(min <= max){
            // console.log('次循环') // 循环次数统计
            const middleIndex = Math.floor((min + max) / 2)
            const middleItem  = this.prefixSum[middleIndex]
            if(middleItem < about){
                let nextItem = this.prefixSum[middleIndex + 1]
                if(!nextItem || nextItem > about){
                    // return middleIndex + 1 // 例如 使用 45 查找 前缀和 [30, 40, 50]，将返回40的下标1， 而不是50的2，向上取值
                    return middleIndex 
                }
                min = middleIndex + 1
            }else if(middleItem > about){
                if(this.prefixSum[middleIndex - 1] < about){
                    return middleIndex - 1
                }
                max = middleIndex - 1
            }else {
                return middleIndex
            }
        }
        return 0
    }
    
    /**
     * 计算前缀和
     * @param {Array} pre 计算数组
     * @param {Number} startPoint 起点
     * @return {Array} 前缀和数组
     */
    calculPrefixSum(pre = [], startPoint = 0){
        let result = []
        pre.reduce((sum, present, index) => {
            sum += present
            result.push(sum)
            return sum
        }, startPoint)
        return result
    }
}
export default PrefixSumManage